﻿Public Class Receiver
    Inherits ObservableImpl
    Implements NamedStatusObservable
    Implements TimeObserver
    Implements Resetable
    Private Const MAX_ESTIMATION = 10
    Private status As ReceiverStatus = ReceiverStatus.Idle
    Private name As String
    Private currentCommand As Command
    Private currentExecutionStep As Integer = 0
    Private totalEstimationSteps As Integer = 0

    Public Sub New(ByVal aName As String)
        name = aName
    End Sub

    Function getStatusDescription() As String Implements NamedStatusObservable.getStatusDescription
        Select Case status
            Case ReceiverStatus.Idle
                Return "Idle"
            Case ReceiverStatus.Processing
                Return currentCommand.getName()
            Case ReceiverStatus.Done
                Return "Done"
        End Select
        Return ""
    End Function

    Function getName() As String Implements NamedStatusObservable.getName
        Return name
    End Function

    Public Sub executeCommand(ByRef command As Command)
        currentCommand = command
        setRandomEstimation()
        currentExecutionStep = 0
    End Sub

    Private Sub setRandomEstimation()
        totalEstimationSteps = CInt(Math.Ceiling(Rnd() * MAX_ESTIMATION))
    End Sub

    Private Sub stepExecution()
        If currentCommand Is Nothing Then
            status = ReceiverStatus.Idle
        ElseIf currentExecutionStep >= totalEstimationSteps Then
            status = ReceiverStatus.Done
            resetCurrentCommand()
        Else
            status = ReceiverStatus.Processing
            currentExecutionStep += 1
        End If
    End Sub

    Private Sub resetCurrentCommand()
        currentCommand = Nothing
        currentExecutionStep = 0
        totalEstimationSteps = 0
    End Sub

    Sub timeNotification() Implements TimeObserver.timeNotification
        stepExecution()
        NotifyObservers()
    End Sub

    Public Sub reset() Implements Resetable.reset
        resetCurrentCommand()
        status = ReceiverStatus.Idle
        NotifyObservers()
    End Sub

    Public Function isAvailable()
        Return status = ReceiverStatus.Idle And currentCommand Is Nothing
    End Function

    Public Function getTotalEstimation() As Integer
        Return totalEstimationSteps
    End Function

    Public Function isProcessing() As Boolean
        Return status = ReceiverStatus.Processing
    End Function

    Public Function isDone() As Boolean
        Return status = ReceiverStatus.Done
    End Function

    Public Function getCurrentCommand() As Command
        Return currentCommand
    End Function
End Class
